bitkeeper revision 1.1488.1.1 (428e39badumj52vi-nzb7GBmoVe2dA)
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Fri, 20 May 2005 19:25:46 +0000 (19:25 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Fri, 20 May 2005 19:25:46 +0000 (19:25 +0000)
XendDomainInfo.py, XendDomain.py, xc.c, xc_linux_restore.c, xc.h:
  Implement the parts of vm restore which need interaction with xend
  as part of xend, instead of using xfrd.  The restore functionality
  using xfrd was broken anyway since xend didn't handle the callback
  channel from xfrd correctly.
xen_domain.c:
  Disable restore in xfrd.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
tools/libxc/xc.h
tools/libxc/xc_linux_restore.c
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/xfrd/xen_domain.c

index 591f9ae187e2950c49352e1870348f3364c5e588..99b55f50b508b358070977e48d2ad77d7b67ff04 100644 (file)
@@ -244,7 +244,8 @@ int xc_linux_save(int xc_handle, struct XcIOContext *ioctxt);
  * @parm ioctxt the IO context to restore a domain from
  * @return 0 on success, -1 on failure
  */
-int xc_linux_restore(int xc_handle, struct XcIOContext *ioctxt);
+int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
+                    unsigned char *pfn2mfn);
 
 int xc_linux_build(int xc_handle,
                    u32 domid,
index afabadb17adaf109fa63633edfaf1b10437fa9bc..fe92441511d51c6ac3a961e4a6c00e8af8211cb7 100644 (file)
 
 #define DEBUG 0
 
+#if 1
+#define ERR(_f, _a...) fprintf ( stderr, _f , ## _a )
+#else
+#define ERR(_f, _a...) ((void)0)
+#endif
+
 #if DEBUG
-#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#define DPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a )
 #else
 #define DPRINTF(_f, _a...) ((void)0)
 #endif
 
-/** Read the vmconfig string from the state input.
- * It is stored as a 4-byte count 'n' followed by n bytes.
- * The config data is stored in a new string in 'ioctxt->vmconfig',
- * and is null-terminated. The count is stored in 'ioctxt->vmconfig_n'.
- *
- * @param ioctxt i/o context
- * @return 0 on success, non-zero on error.
- */
-static int read_vmconfig(XcIOContext *ioctxt)
-{
-    int err = -1;
-
-    if ( xcio_read(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n)) )
-        goto exit;
-
-    ioctxt->vmconfig = malloc(ioctxt->vmconfig_n + 1);
-    if ( ioctxt->vmconfig == NULL ) 
-        goto exit;
-
-    if ( xcio_read(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n) )
-        goto exit;
-
-    ioctxt->vmconfig[ioctxt->vmconfig_n] = '\0';
-    err = 0;
-
-  exit:
-    if ( err )
-    {
-        if ( ioctxt->vmconfig != NULL )
-            free(ioctxt->vmconfig);
-        ioctxt->vmconfig = NULL;
-        ioctxt->vmconfig_n = 0;
-    }
-    return err;
-}
+#define PROGRESS 0
+#if PROGRESS
+#define PPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a )
+#else
+#define PPRINTF(_f, _a...)
+#endif
 
-int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
+int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
+                     unsigned char *pfn2mfn)
 {
     dom0_op_t op;
     int rc = 1, i, n, k;
     unsigned long mfn, pfn, xpfn;
     unsigned int prev_pc, this_pc;
-    u32 dom = 0;
-    int verify = 0; 
-
-    /* Number of page frames in use by this Linux session. */
-    unsigned long nr_pfns;
+    int verify = 0;
+    int err;
 
     /* The new domain's shared-info frame number. */
     unsigned long shared_info_frame;
@@ -75,9 +50,6 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
     /* A copy of the CPU context of the guest. */
     vcpu_guest_context_t ctxt;
 
-    /* First 16 bytes of the state file must contain 'LinuxGuestRecord'. */
-    char signature[16];
-    
     /* A table containg the type of each PFN (/not/ MFN!). */
     unsigned long *pfn_type = NULL;
 
@@ -88,7 +60,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
     unsigned long *ppage = NULL;
 
     /* A copy of the pfn-to-mfn table frame list. */
-    unsigned long pfn_to_mfn_frame_list[1024];
+    unsigned long *pfn_to_mfn_frame_list = (void *)pfn2mfn; // [1024];
 
     /* A table mapping each PFN to its new MFN. */
     unsigned long *pfn_to_mfn_table = NULL;
@@ -110,126 +82,68 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
     struct mmuext_op pin[MAX_PIN_BATCH];
     unsigned int nr_pins = 0;
 
-    xcio_info(ioctxt, "xc_linux_restore start\n");
+    DPRINTF("xc_linux_restore start\n");
 
-    if ( mlock(&ctxt, sizeof(ctxt) ) )
-    {
+    if (mlock(&ctxt, sizeof(ctxt))) {
         /* needed for when we do the build dom0 op, 
            but might as well do early */
-        PERROR("Unable to mlock ctxt");
+        ERR("Unable to mlock ctxt");
         return 1;
     }
 
-    /* Start reading the saved-domain record. */
-    if ( xcio_read(ioctxt, signature, 16) ||
-         (memcmp(signature, "LinuxGuestRecord", 16) != 0) )
-    {
-        xcio_error(ioctxt, "Unrecognised state format -- no signature found");
-        goto out;
-    }
-
-    if ( xcio_read(ioctxt, &nr_pfns,              sizeof(unsigned long)) ||
-         xcio_read(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) )
-    {
-        xcio_error(ioctxt, "Error reading header");
-        goto out;
-    }
-
-    if ( read_vmconfig(ioctxt) )
-    {
-        xcio_error(ioctxt, "Error writing vmconfig");
-        goto out;
-    }
-
-    if ( nr_pfns > 1024*1024 )
-    {
-        xcio_error(ioctxt, "Invalid state file -- pfn count out of range");
-        goto out;
-    }
-
     /* We want zeroed memory so use calloc rather than malloc. */
-    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
-    pfn_type         = calloc(1, 4 * nr_pfns);    
-    region_mfn       = calloc(1, 4 * MAX_BATCH_SIZE);    
+    pfn_to_mfn_table = calloc(4, nr_pfns);
+    pfn_type = calloc(4, nr_pfns);    
+    region_mfn = calloc(4, MAX_BATCH_SIZE);
 
-    if ( (pfn_to_mfn_table == NULL) ||
-         (pfn_type == NULL) || 
-         (region_mfn == NULL) ) 
-    {
+    if ((pfn_to_mfn_table == NULL) || (pfn_type == NULL) || 
+        (region_mfn == NULL)) {
+        ERR("memory alloc failed");
         errno = ENOMEM;
         goto out;
     }
     
-    if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) )
-    {
-        xcio_error(ioctxt, "Could not mlock region_mfn");
+    if (mlock(region_mfn, 4 * MAX_BATCH_SIZE)) {
+        ERR("Could not mlock region_mfn");
         goto out;
     }
 
-    /* Create domain on CPU -1 so that it may auto load-balance in future. */
-    if ( xc_domain_create(xc_handle, &dom) )
-    {
-        xcio_error(ioctxt, "Could not create domain.");
-        goto out;
-    }
-    if ( xc_domain_setcpuweight(xc_handle, dom, 1) )
-    {
-        xcio_error(ioctxt, "Could not set domain cpuweight.");
-        goto out;
-    }
-    if ( xc_domain_setmaxmem(xc_handle, dom, nr_pfns * (PAGE_SIZE / 1024)) )
-    {
-        xcio_error(ioctxt, "Could not set domain maxmem. pfns=%ld, %ldKB",
-                   nr_pfns, nr_pfns * (PAGE_SIZE / 1024));
-        goto out;
-    }
-    if ( xc_domain_memory_increase_reservation(xc_handle, dom,
-                                               nr_pfns * (PAGE_SIZE / 1024)) )
-    {
-        xcio_error(ioctxt,
-                   "Could not increase domain memory reservation. pfns=%ld",
-                   nr_pfns);
-        goto out;
-    }
-
-    ioctxt->domain = dom;
-    xcio_info(ioctxt, "Created domain %u\n", dom);
-
     /* Get the domain's shared-info frame. */
     op.cmd = DOM0_GETDOMAININFO;
     op.u.getdomaininfo.domain = (domid_t)dom;
-    if ( do_dom0_op(xc_handle, &op) < 0 )
-    {
-        xcio_error(ioctxt, "Could not get information on new domain");
+    if (do_dom0_op(xc_handle, &op) < 0) {
+        ERR("Could not get information on new domain");
         goto out;
     }
     shared_info_frame = op.u.getdomaininfo.shared_info_frame;
 
-    if(ioctxt->flags & XCFLAGS_CONFIGURE)
-    {
-        if(xcio_configure_domain(ioctxt))
-        {
-           xcio_error(ioctxt, "Configuring domain failed"); 
-           goto out;
-        }
+    err = xc_domain_setmaxmem(xc_handle, dom, nr_pfns * PAGE_SIZE / 1024);
+    if (err != 0) {
+        errno = ENOMEM;
+        goto out;
+    }
+
+    err = xc_domain_memory_increase_reservation(xc_handle, dom,
+                                                nr_pfns * PAGE_SIZE / 1024);
+    if (err != 0) {
+        errno = ENOMEM;
+        goto out;
     }
 
     /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
-    if ( xc_get_pfn_list(xc_handle, dom, 
-                         pfn_to_mfn_table, nr_pfns) != nr_pfns )
-    {
-        xcio_error(ioctxt, "Did not read correct number of frame "
-                   "numbers for new dom");
+    if (xc_get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) !=
+        nr_pfns) {
+        ERR("Did not read correct number of frame numbers for new dom");
         goto out;
     }
 
-    if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
-    {
-        xcio_error(ioctxt, "Could not initialise for MMU updates");
+    mmu = init_mmu_updates(xc_handle, dom);
+    if (mmu == NULL) {
+        ERR("Could not initialise for MMU updates");
         goto out;
     }
 
-    xcio_info(ioctxt, "Reloading memory pages:   0%%");
+    DPRINTF("Reloading memory pages:   0%%");
 
     /*
      * Now simply read each saved frame into its new machine frame.
@@ -246,17 +160,17 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
         this_pc = (n * 100) / nr_pfns;
         if ( (this_pc - prev_pc) >= 5 )
         {
-            xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc);
+            PPRINTF("\b\b\b\b%3d%%", this_pc);
             prev_pc = this_pc;
         }
 
-        if ( xcio_read(ioctxt, &j, sizeof(int)) )
+        if ( read(io_fd, &j, sizeof(int)) != sizeof(int) )
         {
-            xcio_error(ioctxt, "Error when reading from state file");
+            ERR("Error when reading from state file");
             goto out;
         }
 
-        DPRINTF("batch %d\n",j);
+        PPRINTF("batch %d\n",j);
  
         if ( j == -1 )
         {
@@ -270,12 +184,13 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
 
         if ( j > MAX_BATCH_SIZE )
         {
-            xcio_error(ioctxt, "Max batch size exceeded. Giving up.");
+            ERR("Max batch size exceeded. Giving up.");
             goto out;
         }
  
-        if ( xcio_read(ioctxt, region_pfn_type, j*sizeof(unsigned long)) ) {
-            xcio_error(ioctxt, "Error when reading from state file");
+        if ( read(io_fd, region_pfn_type, j*sizeof(unsigned long)) !=
+             j*sizeof(unsigned long) ) {
+            ERR("Error when reading from state file");
             goto out;
         }
 
@@ -297,7 +212,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
                                                   region_mfn,
                                                   j )) == 0 )
         {
-            xcio_error(ioctxt, "map batch failed");
+            ERR("map batch failed");
             goto out;
         }
 
@@ -311,7 +226,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
 
             if (pfn>nr_pfns)
             {
-                xcio_error(ioctxt, "pfn out of range");
+                ERR("pfn out of range");
                 goto out;
             }
 
@@ -326,9 +241,9 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
             else
                 ppage = (unsigned long*) (region_base + i*PAGE_SIZE);
 
-            if ( xcio_read(ioctxt, ppage, PAGE_SIZE) )
+            if ( read(io_fd, ppage, PAGE_SIZE) != PAGE_SIZE )
             {
-                xcio_error(ioctxt, "Error when reading from state file");
+                ERR("Error when reading from state file");
                 goto out;
             }
 
@@ -346,7 +261,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
                         xpfn = ppage[k] >> PAGE_SHIFT;
                         if ( xpfn >= nr_pfns )
                         {
-                            xcio_error(ioctxt, "Frame number in type %lu page "
+                            ERR("Frame number in type %lu page "
                                        "table is out of range. i=%d k=%d "
                                        "pfn=0x%lx nr_pfns=%lu", 
                                        region_pfn_type[i]>>28, i, 
@@ -374,7 +289,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
 
                         if ( xpfn >= nr_pfns )
                         {
-                            xcio_error(ioctxt, "Frame number in type %lu page"
+                            ERR("Frame number in type %lu page"
                                        " table is out of range. i=%d k=%d "
                                        "pfn=%lu nr_pfns=%lu",
                                        region_pfn_type[i]>>28, i, k, 
@@ -391,7 +306,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
             break;
 
             default:
-                xcio_error(ioctxt, "Bogus page type %lx page table is "
+                ERR("Bogus page type %lx page table is "
                            "out of range. i=%d nr_pfns=%lu", 
                            region_pfn_type[i], i, nr_pfns);
                 goto out;
@@ -432,7 +347,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
         n+=j; /* crude stats */
     }
 
-    xcio_info(ioctxt, "Received all pages\n");
+    DPRINTF("Received all pages\n");
 
     if ( finish_mmu_updates(xc_handle, mmu) )
         goto out;
@@ -462,30 +377,31 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
          (do_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) )
         goto out;
 
-    xcio_info(ioctxt, "\b\b\b\b100%%\n");
-    xcio_info(ioctxt, "Memory reloaded.\n");
+    DPRINTF("\b\b\b\b100%%\n");
+    DPRINTF("Memory reloaded.\n");
 
     /* Get the list of PFNs that are not in the psuedo-phys map */
     {
        unsigned int count, *pfntab;
        int rc;
 
-       if ( xcio_read(ioctxt, &count, sizeof(count)) )
+       if ( read(io_fd, &count, sizeof(count)) != sizeof(count) )
        {
-           xcio_error(ioctxt, "Error when reading from state file");
+           ERR("Error when reading from state file");
            goto out;
        }
 
        pfntab = malloc( sizeof(unsigned int) * count );
        if ( pfntab == NULL )
        {
-           xcio_error(ioctxt, "Out of memory");
+           ERR("Out of memory");
            goto out;
        }
 
-       if ( xcio_read(ioctxt, pfntab, sizeof(unsigned int)*count) )
+       if ( read(io_fd, pfntab, sizeof(unsigned int)*count) !=
+             sizeof(unsigned int)*count )
        {
-           xcio_error(ioctxt, "Error when reading pfntab from state file");
+           ERR("Error when reading pfntab from state file");
            goto out;
        }
 
@@ -502,7 +418,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
                                       MEMOP_decrease_reservation,
                                       pfntab, count, 0, dom )) <0 )
            {
-               xcio_error(ioctxt, "Could not decrease reservation : %d",rc);
+               ERR("Could not decrease reservation : %d",rc);
                goto out;
            }
            else
@@ -512,10 +428,10 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
        }       
     }
 
-    if ( xcio_read(ioctxt, &ctxt,            sizeof(ctxt)) ||
-         xcio_read(ioctxt, shared_info_page, PAGE_SIZE) )
+    if ( read(io_fd, &ctxt,            sizeof(ctxt)) != sizeof(ctxt) ||
+         read(io_fd, shared_info_page, PAGE_SIZE) != PAGE_SIZE )
     {
-        xcio_error(ioctxt, "Error when reading from state file");
+        ERR("Error when reading from state file");
         goto out;
     }
 
@@ -523,7 +439,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
     pfn = ctxt.user_regs.esi;
     if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) )
     {
-        xcio_error(ioctxt, "Suspend record frame number is bad");
+        ERR("Suspend record frame number is bad");
         goto out;
     }
     ctxt.user_regs.esi = mfn = pfn_to_mfn_table[pfn];
@@ -537,7 +453,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
     /* Uncanonicalise each GDT frame number. */
     if ( ctxt.gdt_ents > 8192 )
     {
-        xcio_error(ioctxt, "GDT entry count out of range");
+        ERR("GDT entry count out of range");
         goto out;
     }
 
@@ -546,7 +462,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
         pfn = ctxt.gdt_frames[i];
         if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) )
         {
-            xcio_error(ioctxt, "GDT frame number is bad");
+            ERR("GDT frame number is bad");
             goto out;
         }
         ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
@@ -558,7 +474,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
     {
         printf("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx\n",
                pfn, nr_pfns, pfn_type[pfn], (unsigned long)L2TAB);
-        xcio_error(ioctxt, "PT base is bad.");
+        ERR("PT base is bad.");
         goto out;
     }
     ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
@@ -583,7 +499,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
         pfn = pfn_to_mfn_frame_list[i];
         if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) )
         {
-            xcio_error(ioctxt, "PFN-to-MFN frame number is bad");
+            ERR("PFN-to-MFN frame number is bad");
             goto out;
         }
         mfn = pfn_to_mfn_table[pfn];
@@ -596,7 +512,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
                                pfn_to_mfn_frame_list,
                                (nr_pfns+1023)/1024 )) == 0 )
     {
-        xcio_error(ioctxt, "Couldn't map pfn_to_mfn table");
+        ERR("Couldn't map pfn_to_mfn table");
         goto out;
     }
 
@@ -636,11 +552,11 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
          (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
          ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
     {
-        xcio_error(ioctxt, "Bad LDT base or size");
+        ERR("Bad LDT base or size");
         goto out;
     }
 
-    xcio_info(ioctxt, "Domain ready to be built.\n");
+    DPRINTF("Domain ready to be built.\n");
 
     op.cmd = DOM0_SETDOMAININFO;
     op.u.setdomaininfo.domain = (domid_t)dom;
@@ -650,26 +566,20 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
 
     if ( rc != 0 )
     {
-        xcio_error(ioctxt, "Couldn't build the domain");
+        ERR("Couldn't build the domain");
         goto out;
     }
 
-    if ( ioctxt->flags & XCFLAGS_CONFIGURE )
-    {
-        xcio_info(ioctxt, "Domain ready to be unpaused\n");
-        op.cmd = DOM0_UNPAUSEDOMAIN;
-        op.u.unpausedomain.domain = (domid_t)dom;
-        rc = do_dom0_op(xc_handle, &op);
-    }
-
-    if ( rc == 0 )
-    {
+    DPRINTF("Domain ready to be unpaused\n");
+    op.cmd = DOM0_UNPAUSEDOMAIN;
+    op.u.unpausedomain.domain = (domid_t)dom;
+    rc = do_dom0_op(xc_handle, &op);
+    if (rc == 0) {
         /* Success: print the domain id. */
-        xcio_info(ioctxt, "DOM=%u\n", dom);
+        DPRINTF("DOM=%u\n", dom);
         return 0;
     }
 
-
  out:
     if ( (rc != 0) && (dom != 0) )
         xc_domain_destroy(xc_handle, dom);
@@ -680,9 +590,6 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
     if ( pfn_type != NULL )
         free(pfn_type);
 
-    if ( rc == 0 )
-        ioctxt->domain = dom;
-
-    DPRINTF("Restore exit with rc=%d\n",rc);
+    DPRINTF("Restore exit with rc=%d\n", rc);
     return rc;
 }
index 39045370c7303bbe38c32c605d75be33b9a9d196..b1dff53a87116d5b201bef289a430934b01fc119 100644 (file)
@@ -334,62 +334,41 @@ static PyObject *pyxc_linux_save(PyObject *self,
     return val;
 }
 
-
-static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file)
-{
-    int rc = -1;
-
-    ioctxt->io = gzip_stream_fopen(state_file, "rb");
-    if ( ioctxt->io == NULL )
-    {
-        xcio_perror(ioctxt, "Could not open file for reading");
-        return rc;
-    }
-
-    rc = xc_linux_restore(xc->xc_handle, ioctxt);
-
-    IOStream_close(ioctxt->io);
-    
-    return rc;
-}
-
 static PyObject *pyxc_linux_restore(PyObject *self,
                                     PyObject *args,
                                     PyObject *kwds)
 {
     XcObject *xc = (XcObject *)self;
-    char *state_file;
-    int progress = 1, debug = 0;
     PyObject *val = NULL;
-    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
     int rc =-1;
+    int io_fd, dom;
+    unsigned long nr_pfns;
+    char *pfn2mfn;
+    int pfn2mfn_len;
+    PyObject *pfn2mfn_object;
 
-    static char *kwd_list[] = { "state_file", "progress", "debug", NULL };
+    static char *kwd_list[] = { "fd", "dom", "pfns", "pfn2mfn", NULL };
 
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s|ii", kwd_list,
-                                      &state_file,
-                                      &progress,
-                                      &debug) )
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iilO", kwd_list,
+                                      &io_fd, &dom, &nr_pfns,
+                                     &pfn2mfn_object) )
         goto exit;
 
-    if ( progress )
-        ioctxt.flags |= XCFLAGS_VERBOSE;
-    if ( debug )
-        ioctxt.flags |= XCFLAGS_DEBUG;
+    if (PyString_AsStringAndSize(pfn2mfn_object, &pfn2mfn, &pfn2mfn_len))
+       goto exit;
 
-    if ( (state_file == NULL) || (state_file[0] == '\0') )
-        goto exit;
+    if (pfn2mfn_len != PAGE_SIZE)
+       goto exit;
 
-    rc = file_restore(xc, &ioctxt, state_file);
+    rc = xc_linux_restore(xc->xc_handle, io_fd, dom, nr_pfns, pfn2mfn);
     if ( rc != 0 )
     {
         PyErr_SetFromErrno(xc_error);
         goto exit;
     }
 
-    val = Py_BuildValue("{s:i,s:s}",
-                        "dom", ioctxt.domain,
-                        "vmconfig", ioctxt.vmconfig);
+    Py_INCREF(zero);
+    val = zero;
 
   exit:
     return val;
@@ -1061,8 +1040,9 @@ static PyMethodDef pyxc_methods[] = {
       (PyCFunction)pyxc_linux_restore, 
       METH_VARARGS | METH_KEYWORDS, "\n"
       "Restore the CPU and memory state of a Linux guest OS.\n"
-      " state_file [str]:    Name of state file. Must not currently exist.\n"
-      " progress   [int, 1]: Bool - display a running progress indication?\n\n"
+      " dom        [int]:    Identifier of domain to be restored.\n"
+      " pfns       [int]:    Number of pages domain uses.\n"
+      " pfn2mfn    [str]:    String containing the pfn to mfn frame list.\n\n"
       "Returns: [int] new domain identifier on success; -1 on error.\n" },
 
     { "linux_build", 
index 24f8cdd31aeaf2f84152007f699cfe621202c274..91ae01f85adfc91274fb7c7731b81dee72a0daf4 100644 (file)
@@ -24,6 +24,9 @@ import scheduler
 from xen.xend.server import channel
 
 
+import errno
+from struct import pack, unpack, calcsize
+
 __all__ = [ "XendDomain" ]
 
 SHUTDOWN_TIMEOUT = 30
@@ -298,7 +301,7 @@ class XendDomain:
                            [dominfo.name, dominfo.id, "fail"])
         return dominfo
 
-    def domain_configure(self, id, vmconfig):
+    def domain_configure(self, vmconfig):
         """Configure an existing domain. This is intended for internal
         use by domain restore and migrate.
 
@@ -306,10 +309,7 @@ class XendDomain:
         @param vmconfig: vm configuration
         """
         config = sxp.child_value(vmconfig, 'config')
-        dominfo = self.domain_lookup(id)
-        log.debug('domain_configure> id=%s config=%s', str(id), str(config))
-        if dominfo.config:
-            raise XendError("Domain already configured: " + dominfo.id)
+        dominfo = XendDomainInfo.tmp_restore_create_domain()
         dominfo.dom_construct(dominfo.dom, config)
         self._add_domain(dominfo)
         return dominfo
@@ -320,8 +320,65 @@ class XendDomain:
         @param src:      source file
         @param progress: output progress if true
         """
-        xmigrate = XendMigrate.instance()
-        return xmigrate.restore_begin(src)
+
+        SIGNATURE = "LinuxGuestRecord"
+        sizeof_int = calcsize("L")
+        sizeof_unsigned_long = calcsize("i")
+        PAGE_SIZE = 4096
+
+        class XendFile(file):
+            def read_exact(self, size, error_msg):
+                buf = self.read(size)
+                if len(buf) != size:
+                    raise XendError(error_msg)
+                return buf
+        
+        try:
+            fd = XendFile(src, 'rb')
+
+            signature = fd.read_exact(len(SIGNATURE),
+                "not a valid guest state file: signature read")
+            if signature != SIGNATURE:
+                raise XendError("not a valid guest state file: found '%s'" %
+                                signature)
+
+            l = fd.read_exact(sizeof_unsigned_long,
+                              "not a valid guest state file: pfn count read")
+            nr_pfns = unpack("=L", l)[0]   # XXX endianess
+            if nr_pfns > 1024*1024:     # XXX
+                raise XendError(
+                    "not a valid guest state file: pfn count out of range")
+
+            pfn_to_mfn_frame_list = fd.read_exact(PAGE_SIZE,
+                "not a valid guest state file: pfn_to_mfn_frame_list read")
+
+            l = fd.read_exact(sizeof_int,
+                              "not a valid guest state file: config size read")
+            vmconfig_size = unpack("i", l)[0] # XXX endianess
+            vmconfig_buf = fd.read_exact(vmconfig_size,
+                "not a valid guest state file: config read")
+
+            p = sxp.Parser()
+            p.input(vmconfig_buf)
+            if not p.ready:
+                raise XendError("not a valid guest state file: config parse")
+
+            vmconfig = p.get_val()
+            dominfo = self.domain_configure(vmconfig)
+
+            # XXXcl hack: fd.tell will sync up the object and
+            #             underlying file descriptor
+            ignore = fd.tell()
+
+            xc.linux_restore(fd.fileno(), int(dominfo.id), nr_pfns,
+                             pfn_to_mfn_frame_list)
+            return dominfo
+
+        except IOError, ex:
+            if ex.errno == errno.ENOENT:
+                raise XendError("can't open guest state file %s" % src)
+            else:
+                raise
     
     def domain_get(self, id):
         """Get up-to-date info about a domain.
index 8383ee74703661f27fa5a16cefe195200a6abf52..e87f8d32114155cced0a9be4e8b0061f034a9576 100644 (file)
@@ -183,6 +183,13 @@ def vm_create(config):
     vm.construct(config)
     return vm
 
+def tmp_restore_create_domain():
+    # dom input parameter is ignored
+    vm = XendDomainInfo()
+    dom = xc.domain_create()
+    vm.setdom(dom)
+    return vm
+
 def vm_recreate(savedinfo, info):
     """Create the VM object for an existing domain.
 
index 9f9d1f15a6d3fc6e50bbf5838e9ae900679c40c7..fb2951555ac7538d42d138b2bc62873b308c6ff3 100644 (file)
@@ -87,6 +87,7 @@ int xen_domain_rcv(IOStream *io,
                    char **vmconfig, int *vmconfig_n,
                    int *configured){
     int err = 0;
+#if 0
     XcIOContext _ioctxt = {}, *ioctxt = &_ioctxt;
     dprintf(">\n");
     ioctxt->io = io;
@@ -102,6 +103,7 @@ int xen_domain_rcv(IOStream *io,
     *vmconfig_n = ioctxt->vmconfig_n;
     *configured = (ioctxt->flags & XCFLAGS_CONFIGURE);
     dprintf("< err=%d\n", err);
+#endif
     return err;
 }